package cn.jdemo.juc.brief.sdk.bean.copier.provider;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;

import cn.jdemo.juc.brief.sdk.bean.copier.anno.AnnoCopyAlias;
import cn.jdemo.juc.brief.sdk.bean.copier.util.BeanCopyUtil;

/**
 * @desc 1) 处理实体类间字段赋值
 * 		 2) 实体类间字段不对应,则加主键予以对应 
 * 		 3) 针对类型转换相关问题,处理基本类型转换相关
 *       ... ...
 * @author zhangliuwei
 * 
 */
public class CopyEntity {

	/**
	 * 源对象|数据源
	 */
	private Object source;
	
	/**
	 * 目标对象|被赋值对象
	 */
	private Object dest;

	/**
	 * TODO:参数扩展[例如:需要排除赋值字段之类的...] | 或者对注解(AnnoCopyAlias)进行扩展也可以
	 */
	// private final CopyOptions copyOptions;
	private final Class<?> sourceClass;
	private final Class<?> destClass;

	public CopyEntity(Object source, Object dest) {
		super();
		this.source = source;
		this.dest = dest;
		this.sourceClass = source.getClass();
		this.destClass = dest.getClass();
	}

	/**
	 * @desc 1) 数据类型转换_可扩展
	 *       2) 主要处理的是基本数据类型
	 *       3) 注:主要处理二者数据类型不一致的情况
	 * 
	 * @param fldSourcetype
	 * @param sourceObj
	 * @param fldDesttype
	 * @return
	 */
	public Object wrapperFieldVal(String fldSourcetype, Object sourceObj, String fldDesttype) {
		if (fldSourcetype==null || sourceObj == null || fldDesttype==null) {
			return null;
		}
		if (fldSourcetype.equals(fldDesttype)) {
			return sourceObj;
		}
		Object destObj = null;
		if ("String".equals(fldDesttype)) {
			destObj = String.valueOf(sourceObj);
		} else if ("Double".equals(fldDesttype)) {
			destObj =  Double.valueOf(String.valueOf(sourceObj));
		} else if ("double".equals(fldDesttype)) {
			destObj =  Double.valueOf(String.valueOf(sourceObj));
		} else if ("Integer".equals(fldDesttype)) {
			destObj =  Integer.valueOf(String.valueOf(sourceObj));
		} else if ("int".equals(fldDesttype)) {
			destObj =  Integer.valueOf(String.valueOf(sourceObj));
		} else if ("Long".equals(fldDesttype)) {
			destObj =  Long.valueOf(String.valueOf(sourceObj));
		} else if ("long".equals(fldDesttype)) {
			destObj =  Long.valueOf(String.valueOf(sourceObj));
		} else if ("BigDecimal".equals(fldDesttype)) {
			destObj =  new BigDecimal(String.valueOf(sourceObj));
		} else if ("Float".equals(fldDesttype)) {
			destObj =  new Float(String.valueOf(sourceObj));
		} else if ("float".equals(fldDesttype)) {
			destObj =  new Float(String.valueOf(sourceObj));
		}
		// 处理时间格式和字符串之间的转化
		if ("Date".equals(fldSourcetype) && "String".equals(fldDesttype)) {
			destObj = BeanCopyUtil.date2String((Date) sourceObj);
		}
		if ("String".equals(fldSourcetype) && "Date".equals(fldDesttype)) {
			// destObj = BeanCopyUtil.string2Date(String.valueOf(sourceObj)); // yyyy-MM-dd HH:mm:ss,暂按这个模式处理
		}
		// 继续扩展ing...
		return destObj;
	}
	
	/**
	 * 对象赋值
	 * 
	 * @param list
	 * @return
	 */
	public Object convertToBean() throws Exception {
		
		Field[] fields = BeanCopyUtil.getFields(sourceClass);
		Field[] fieldDests = BeanCopyUtil.getFields(destClass);

		for (Field field : fields) {
			for (Field fieldDest : fieldDests) {
				Boolean isMatch = false;
				if (fieldDest.isAnnotationPresent(AnnoCopyAlias.class)) {
					// 字段注解匹配
					AnnoCopyAlias fieldAnno = fieldDest.getAnnotation(AnnoCopyAlias.class);
					if (!(fieldAnno.value().toString()).equals(field.getName())) {
						continue;
					}
					isMatch = true;
				} else {
					// 字段名称匹配
					if (!(fieldDest.getName()).equals(field.getName())) {
						continue;
					}
					isMatch = true;
				}
				
				if (isMatch) {
					// 获取源字段数据
					Method getterMethod = BeanCopyUtil.getGetterMethod(sourceClass, field);
					if (getterMethod == null) {
						continue;
					}
					Object sourceObj = getterMethod.invoke(source);
					
					// 处理目标字段
					Method setterMethod = BeanCopyUtil.getSetterMethod(destClass, fieldDest);
					if (setterMethod == null) {
						continue;
					}
					String fldDesttype = fieldDest.getType().getSimpleName();
					String fldSourcetype = field.getType().getSimpleName();
					Object destObj = null;
					if (!(fldSourcetype).equals(fldDesttype) && sourceObj != null) {
						destObj = this.wrapperFieldVal(fldSourcetype, sourceObj, fldDesttype);// 类型转换
						if (destObj==null) {
							throw new Exception("类型转换匹配失败，扩展ing...");
						}
					}else {
						destObj = sourceObj;
					}
					setterMethod.setAccessible(true);
					setterMethod.invoke(dest, destObj);
				}
			}
		}
		return dest;
	}
}
